# This is a sample Python script.

# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
import serial
import serial.tools.list_ports
from main_iic import *
import  time

from threading import Thread
import keyboard
import os,sys

def print_hi(name):
    # Use a breakpoint in the code line below to debug your script.
    print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.



class ser_comm():
    def __init__(self,com,bps,timeout):
        self.port = com
        self.bps = bps
        self.timeout = timeout
        try:
            ser = serial.Serial(self.port,self.bps,timeout=self.timeout)
            if ser.is_open:
                print('ser init true')
            else:
                print('ser init false')
        except:
            print('ser init false')
        pass

def get_ser_list():
    port_list = serial.tools.list_ports.comports()
    print(f'valid ser {len(port_list)}')
    if len(port_list) == 0:
        print('无可用串口')
    else:
        for i in range(0,len(port_list)):
            print(port_list[i])

def ser_monitor():
    pass
def get_serial_port():
    pass
class input_thread(Thread): #键盘处理类
    def __init__(self,iic_odj = None):
        super(input_thread, self).__init__()
        if iic_odj:
            self.iic_obj = iic_odj
    def run(self):
        #self.keyboardListener()
        #return
        cnts = 0
        cntc = 0
        cnte = 0
        cntk = 0
        self.save = False
        self.clear = False
        saving = False
        clearing = False
        while True:
            # r = keyboard.read_key()
            # print(r)
            #k = keyboard.on_release_key('ctrl', self.iic_obj.data_set_save,suppress=True)
            #k = keyboard.on_release_key('ctrl+r', lambda x: os.system('cls'))
            s = keyboard.is_pressed("ctrl+s")
            #print(s)
            if s:
                cnts+=1
                #print(cnts)
                if cnts/1 > 1:
                    self.iic_obj.data_set_save()
                    cnts = 0
            ke = keyboard.is_pressed("ctrl+e")
            # print(s)
            if ke:
                cnte += 1
                # print(cnts)
                if cnte / 1 > 1:
                    self.iic_obj.cal_enable()
                    cnte = 0
            kk = keyboard.is_pressed("ctrl+k")
            if kk:
                cntk += 1
                # print(cnts)
                if cntk / 1 > 1:
                    self.iic_obj.cal_fun()
                    cntk = 0
            c = keyboard.is_pressed("ctrl+r")
            if c:
                cntc += 1
                #print(cntc)
                if cntc / 2 > 1:
                    print('开始清屏')
                    self.clear = True
                    cntc = 0
                if self.clear and not clearing:
                    clearing = True
                    os.system('cls')
                    self.iic_obj.databuff = []
                    self.clear = False
                    clearing = False
                    print('清屏完成')
            #time.sleep(0.01)
            #break
class iic_process(USBI2C):

    def __init__(self, usb_dev = 0, i2c_dev = 0x5c , commfreq = 0x82):
        print('iic_process init')
        super(iic_process, self).__init__(usb_dev, i2c_dev , commfreq)
        self.dev_list = []
        self.dev_connected = False
        self.databuff = []
        self.f = ''
        self.data_t = 0
        self.save = False
        self.sta_invalid = 0xff
        self.sta_ok = 0
        self.calsta = 1
        self.calenable = False
        self.reg = {
            # 寄存器名字:		    (地址，长度)
            'act':				(0x00,1),
            'ver':				(0x01,6),
            'ver_date':			(0x07,10),
            'ir_adc':			(0x11,3),   #首字节为状态位，可以读连续地址
            'ntc_adc':			(0x13,3),   #首字节为状态位，可以读连续地址
            'obj_temp':			(0x15,3),   #首字节为状态位，可以读连续地址
            'ntc_temp':			(0x17,3),   #首字节为状态位，可以读连续地址
            'calvalue_k':		(0x19,4),
            'calvalue_b':		(0x1D,4),
            'cal_point_1_adc':	(0x21,2),
            'cal_point_2_adc':	(0x23,2),
            'cal_ntc_adc':		(0x25,2),
            'cal_sta':			(0x27,2),
            'cal_obj_temp':		(0x29,2),
            'slave_addr':		(0X2B,1),
            'emit_rat':			(0X2C,4),
        }

    def start_nnew_th(self,func,args):
        th = Thread(target=func,args=args)
        th.start()

    def iic_dev_trace(self):
        for x in range(iic_process.dev_addr_start,iic_process.dev_addr_end+1):
            if x%2 != 0: #过滤奇数地址
                continue
            if not self.usb_init:
                break
            self.setdev_addr(x)
            data = self.read(self.reg.get('slave_addr')[0])
            if data == x:
                print(f'dev {hex(x)} exist!!!')
                self.dev_list.append(x)
                self.setdev_addr(x)
                #self.set_usb_freq(0x80)
                self.write(self.reg.get('act')[0], 0x02) #传感器实时更新寄存器
                print('detect mode ',self.readb(self.reg.get('act')[0],self.reg.get('act')[1]))
                self.dev_connected = True
                break
                #return True
            #else:
                #print(f'dev {hex(x)} not exist')
                #return False
            #time.sleep(0.01)
        if not self.dev_list and x == iic_process.dev_addr_end:
            print('no dev exist!!!!!!')
            self.dev_connected = False
            return False
        else:
            self.dev_connected = True
            return  True
    def detect_data_loop(self,reg,cntbyte):
        print('detect_data_loop',self.dev_connected)
        while True and self.dev_connected:
            #print('detect_data_loop', self.dev_connected,self)
            #print('detect_data_loop1')
            data = self.readl(reg, cntbyte)
            self.databuff.append(data)
            # data = master.read(0x00)
            # print(str(data).replace('[','').replace(']',''))
            if self.save:
                self.data_save(self.data_log, data)
            print(data)
            time.sleep(1)
            #print(master)
            # break

    def read_loop(self):
        if self.dev_connected:
            for k,v in self.reg.items():
                print(f'read {k}')
                self.readb(v[0],v[1])
                time.sleep(1)
        else:
            print('no dev connected')
    def cal(self,pt):
        print('cal ',pt)
        v = self.reg.get('act')
        if pt == 1:
            self.write(v[0], 0x08)
        elif pt == 2:
            self.write(v[0], 0x10)
        else:
            print('not valid cal point')
    def input_monitor(self):
        self.t = input_thread(self)
        self.t.start()

    def cal_fun(self):
        enable = self.calenable
        if enable and self.calsta != 3:
            if self.calsta == 1:
                self.cal(1)
                ret = self.readb(self.reg.get('cal_sta')[0],self.reg.get('cal_sta')[1])
                if True:#[0x33,0x33] != ret:
                    self.calsta = 2
                else:
                    print('cal pt1 ng')
            elif self.calsta == 2:
                self.cal(2)
                ret = self.readb(self.reg.get('cal_sta')[0], self.reg.get('cal_sta')[1])
                if [0x33, 0x33] != ret:
                    if ret[0]+ret[1] == 0xff:
                        self.calsta = 3
                else:
                    print('cal pt2 ng')
    def cal_enable(self):
        print('cal_enable')
        v = self.reg.get('act')
        self.write(v[0], 0x04)
        time.sleep(0.2)
        ret = self.read(v[0])
        if  ret == 0x04:
            print('cal en ok')
            self.calenable = True
        else:
            print('cal en ng ',ret)
            self.calenable = False
    def read_reg(self,regname):
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readb(v[0],v[1])
        return data

    def fun_get_ver(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        data = self.read_reg('ver')
        #print(data)
        ver = ''
        vl = [chr(x) for x in data]
        v = ''.join(vl)
        print(v)
        return v
        pass

    def fun_get_ver_date(self):
        data = self.read_reg('ver_date')
        print(data)
        vl = [chr(x) for x in data]
        v = ''.join(vl)
        print(v)
        return v
        pass

    def fun_get_ir_adc(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'ir_adc'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0],v[1])
        if data:
            print(data)
            if data[0] == 170:
                return data
            else:
                print('invalid data')
                return False
        else:
            print('no data')
            return False
        pass
    def fun_get_ntc_adc(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'ntc_adc'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1])
        if data:
            print(data)
            if data[0] == 170:
                return data
            else:
                print('invalid data')
                return False
        else:
            print('no data')
            return False
        pass
    def fun_get_obj_temp(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'obj_temp'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1])
        if data:
            print(data)
            if data[0] == 170:
                return data[1]/10
            else:
                print('invalid data')
                return False
        else:
            print('no data')
            return False
        pass
    def fun_get_ntc_temp(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'ntc_temp'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1])
        if data:
            print(data)
            if data[0] == 170:
                return data[1]/10
            else:
                print('invalid data')
                return False
        else:
            print('no data')
            return False
        pass
    def fun_get_cal_point_1_adc(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'cal_point_1_adc'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1], offset = 0)
        if data:
            print(data)
            return data
        else:
            print('no data')
            return False
        pass
    def fun_get_cal_point_2_adc(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'cal_point_1_adc'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1], offset = 0)
        if data:
            print(data)
            return data
        else:
            print('no data')
            return False
        pass
    def fun_get_cal_ntc_adc(self):
        print(sys._getframe().f_code.co_name)
        time.sleep(self.iic_interval)
        regname = 'cal_ntc_adc'
        if regname not in self.reg.keys():
            print('not valid reg')
            return False
        v = self.reg.get(regname)
        data = self.readl(v[0], v[1], offset = 0)
        if data:
            print(data)
            return data
        else:
            print('no data')
            return False
        pass
    def mkdir(self,path):
        print('创建数据保存文件夹')
        path = path.strip()
        path = path.rstrip("\\")
        isExists = os.path.exists(path)
        if not isExists:
            os.makedirs(path)
            print(path+' 创建成功')#' 创建成功'
            return True
        else:
            # 如果目录存在则不创建，并提示目录已存在
            print(path + ' 目录已存在')
            return False
    def data_set_save(self,key = None):
        if time.time() -self.data_t < 1:
            return
        self.data_t = time.time()
        if self.save:
            self.save = False
            print('关闭保存')
        else:
            self.save = True
            ts = time.strftime("%Y_%m_%d_%H_%M_%S")
            self.data_log =ts
            print('开启保存 ',ts)
    def data_save(self,file,data):
        with open(f'.\log\{file}.txt', 'a+') as f:
            f.writelines(str(data) + '\n')

    def init_console(self):
        print('ctrl+s:保存，ctrl+r:清屏')
        print('[状态位, ir_adc, ntc_adc, 物温, 环温]')

def start_new_th(func,args):
    th = Thread(target=func,args=args)
    th.start()

def iic_dev_monitor():
    global master
    print('iic_dev_monitor')
    if not master:
        master = iic_process()
        print('no master')
    while True:
        while not master.dev_connected: #iic
            print('dev_connected ng')
            while not master.usb_init: #usb
                print('usb init ng')
                master = iic_process() #实时监测
                time.sleep(1)
            #print('usb init ok')
            master.set_usb_freq(0x80)
            master.iic_dev_trace()
            time.sleep(1)
        #print('iic connect ok')
        #print(master)
        time.sleep(1)
        #print('master.dev_connected!!!!!!! ',master.dev_connected)


def master_monitor_loop():
    global master_bak,master
    while True:#False:#True:
        if master_bak != master and master.dev_connected: #matser对象随着usb拔插改变，所以需要监控master对象
            print('new master')
            master_bak = master
            master.init_console()
            print('start detect')
            master.input_monitor()
            master.mkdir('.\log')
            #master.detect_data_loop(0x11,9)
            master.fun_get_ver()
            master.fun_get_ver_date()
            master.fun_get_ir_adc()
            master.fun_get_ntc_adc()
            master.fun_get_obj_temp()
            master.fun_get_ntc_temp()
            master.fun_get_cal_point_1_adc()
            master.fun_get_cal_point_2_adc()
            master.fun_get_cal_ntc_adc()
            #master.start_nnew_th(master.detect_data_loop,(master.reg.get('ir_adc')[0],5))
            #master.start_nnew_th(master.read_loop,())
        time.sleep(5)

if __name__ == '__main__':
    print_hi('PyCharm')
    global master,master_bak
    master_bak = None
    ver = 'I2C Data Process, v1.1, 20200119 by fatri_xm'
    print(ver)
    #get_ser_list()
    master = iic_process()
    #master.input_monitor()
    #iic_dev_thread()
    start_new_th(iic_dev_monitor,())
    start_new_th(master_monitor_loop,())





